//-----------------------------------------------------------------------------
//
//
//-----------------------------------------------------------------------------
#include "EventsEngine.h"
u32 waPeriodicTmrsCounters[MAX_PERIODIC_TIMERS];
u08 baPeriodicTimersReadyList[(MAX_PERIODIC_TIMERS/8)+1];  
u08 baEventFlags[(MAX_EVENTS/8)+1];
u08 baEventsReadyList[(MAX_EVENTS/8)+1];

void vfnEventsEngineInit(void)
{
	u08 lbIndex;
	//Periodic Timers
  	u08 *lbpPtr = &baPeriodicTimersReadyList[0];
  	lbIndex = MAX_PERIODIC_TIMERS - 1;
  	do
  	{
		if(!(lbIndex%8))
		{
			*lbpPtr = 0;
			lbpPtr++;
		}
	}while(lbIndex--);
    lbIndex = (MAX_EVENTS/8);
    do 
    {
      baEventFlags[lbIndex] = 0;
      baEventsReadyList[lbIndex] = 0;      
    }while(lbIndex--);   
}


void vfnEventsEngine(void)
{
	u08 lbIndex;
	u08* bapPtr;
	//Events
	sEvent *ltpEvents = (sEvent *)&taEvents[MAX_EVENTS-1];
	u08* lbpEventsFlags = &baEventFlags[MAX_EVENTS/8];
	lbIndex = MAX_EVENTS-1;
	bapPtr = &baEventsReadyList[MAX_EVENTS/8];
	do
	{
		if((*bapPtr)&gbaBitMask[lbIndex%8])
		{
			if((*lbpEventsFlags)&gbaBitMask[lbIndex%8])
			{
				//Event Acknoledge
				(*lbpEventsFlags) &= ~gbaBitMask[lbIndex%8];
				//Event Callback
				ltpEvents->vfnpCB();
			}
		}
		if(!(lbIndex%8))
		{
			bapPtr--;
			lbpEventsFlags--;			
		}
		ltpEvents--;
	}while(lbIndex--);
}
void vfnPeriodicTimerEnable(u08 bID)
{
	if(MAX_PERIODIC_TIMERS > bID)
	{
		baPeriodicTimersReadyList[(bID/8)] |= gbaBitMask[bID%8];
		waPeriodicTmrsCounters[bID] = taPeriodicTimers[bID].wReloadValue;		
	}
}
void vfnPeriodicTimerDisable(u08 lbID)
{
	if(MAX_PERIODIC_TIMERS > lbID)
	{
		baPeriodicTimersReadyList[(lbID/8)] &= ~gbaBitMask[lbID%8];
	}
}

void vfnEventPost(u08 lbEventID)
{
	if(MAX_EVENTS > lbEventID) 
	{
		u08 lbEventIndex = (u08)(lbEventID/8);
		lbEventID %= 8;
		baEventFlags[lbEventIndex]|=gbaBitMask[lbEventID];
	}
}
void vfnEventEnable(u08 lbEventID)
{
	if(MAX_EVENTS > lbEventID) 
	{
		u08 lbEventIndex = (u08)(lbEventID/8);
		lbEventID %= 8;
		baEventsReadyList[lbEventIndex]|=gbaBitMask[lbEventID];
	}
}
void vfnEventDisable(u08 lbEventID)
{
	if(MAX_EVENTS > lbEventID) 
	{
		u08 lbEventIndex = (u08)(lbEventID/8);
		lbEventID %= 8;
		baEventsReadyList[lbEventIndex]&=~gbaBitMask[lbEventID];
	}
}



void vfnTimeBasedEventsEngine(void)
{
	u08 lbIndex;
	u32 *wapPtr;
	u08* bapPtr;		
	sPeriodicTimers *tpPeriodicTmr = (sPeriodicTimers *)&taPeriodicTimers[MAX_PERIODIC_TIMERS-1];
	wapPtr = &waPeriodicTmrsCounters[MAX_PERIODIC_TIMERS-1];
	lbIndex = MAX_PERIODIC_TIMERS-1;    
	bapPtr = &baPeriodicTimersReadyList[MAX_PERIODIC_TIMERS/8];
	do
	{
		if((*bapPtr)&gbaBitMask[lbIndex%8])
		{
			if(*wapPtr)
    		{
    		  *wapPtr = (u32)(*wapPtr - 1);
    		}
    		else
    		{
				*wapPtr = tpPeriodicTmr->wReloadValue;
				tpPeriodicTmr->vfnpCB();
			}
		}
		wapPtr--;
		tpPeriodicTmr--;  
		if(!(lbIndex%8))
		{
			bapPtr--;		
		}
	}while(lbIndex--);
}
